package com.impress;

import java.util.HashMap;

import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
//import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import android.text.TextUtils;
import android.util.Log;

import com.impress.provider.FeedData;

/**
 * provide access to database
 * @author pluto
 * @version 1.0.2
 * add new field in items:state_pendings
 * @version 2 add summary and download_state field in items
 * @version 3 add preview_img field in items
 */
public class FeedDataProvider extends ContentProvider {

	private static final String TAG = "FeedDataProvider";
	//数据库相关信息
	private static final String DATABASE_NAME = "mobilegr.db";
	/**
	 * 数据库版本号
	 */
	private static final int DATABASE_VERSION = 3;
	
	//表信息
	private static final String ITEMS_TABLE_NAME = "items"; 
	private static final String FEEDS_TABLE_NAME = "feeds";
	private static final String LABELS_TABLE_NAME = "labels";
	private static final String ITEM_LABEL_TABLE_NAME = "item_label";
	
	//MIME Type code(used for uri matching.
	private static final int ITEMS = 1;
	private static final int ITEM_ID = ITEMS + 1;
	private static final int FEEDS = ITEM_ID + 1;
	private static final int FEED_ID = FEEDS + 1;
	private static final int LABELS = FEED_ID + 1;
	private static final int LABEL_ID = LABELS + 1;
	private static final int ITEM_LABELS = LABEL_ID + 1;
	private static final int ITEM_LABEL_ID = ITEM_LABELS + 1;
	
	//may be not use.	
	private static final int ITEMS_BY_LABEL =ITEM_LABEL_ID + 1;
	
	private DatabaseHelper mOpenHelper;
	
	private static final UriMatcher URL_MATCHER;
	//表的列映射
	private static HashMap<String, String> ITEMS_PROJECTION_MAP; 
	private static HashMap<String, String> FEEDS_PROJECTION_MAP;
	private static HashMap<String, String> LABELS_PROJECTION_MAP;
	private static HashMap<String, String> ITEM_LABEL_PROJECTION_MAP;
	
	static{
		//设定uri的match规则
		URL_MATCHER = new UriMatcher(UriMatcher.NO_MATCH);
		URL_MATCHER.addURI(FeedData.AUTHORITY, ITEMS_TABLE_NAME, ITEMS);
		URL_MATCHER.addURI(FeedData.AUTHORITY, ITEMS_TABLE_NAME+"/#", ITEM_ID);
		URL_MATCHER.addURI(FeedData.AUTHORITY, FEEDS_TABLE_NAME, FEEDS);
		URL_MATCHER.addURI(FeedData.AUTHORITY, FEEDS_TABLE_NAME+"/#", FEED_ID);
		URL_MATCHER.addURI(FeedData.AUTHORITY, LABELS_TABLE_NAME, LABELS);
		URL_MATCHER.addURI(FeedData.AUTHORITY, LABELS_TABLE_NAME+"/#", LABEL_ID);
		URL_MATCHER.addURI(FeedData.AUTHORITY, ITEM_LABEL_TABLE_NAME, ITEM_LABELS);
		URL_MATCHER.addURI(FeedData.AUTHORITY, ITEM_LABEL_TABLE_NAME+"/#", ITEM_LABEL_ID);
		URL_MATCHER.addURI(FeedData.AUTHORITY, ITEM_LABEL_TABLE_NAME+"/#", ITEMS_BY_LABEL);
		
		//设定各表列名的映射
		ITEMS_PROJECTION_MAP = new HashMap<String, String>();
		
		ITEMS_PROJECTION_MAP.put(FeedData.Items._ID, 
				ITEMS_TABLE_NAME+"."+FeedData.Items._ID);
		ITEMS_PROJECTION_MAP.put(FeedData.Items.ATOM_ID, 
				ITEMS_TABLE_NAME+"."+FeedData.Items.ATOM_ID);
		ITEMS_PROJECTION_MAP.put(FeedData.Items.CONTENT, 
				ITEMS_TABLE_NAME+"."+FeedData.Items.CONTENT);
		ITEMS_PROJECTION_MAP.put(FeedData.Items.SUMMARY, 
				ITEMS_TABLE_NAME+"."+FeedData.Items.SUMMARY);
		ITEMS_PROJECTION_MAP.put(FeedData.Items.TITLE, 
				ITEMS_TABLE_NAME+"."+FeedData.Items.TITLE);
		ITEMS_PROJECTION_MAP.put(FeedData.Items.ALTERNATE_URL, 
				ITEMS_TABLE_NAME+"."+FeedData.Items.ALTERNATE_URL);
		ITEMS_PROJECTION_MAP.put(FeedData.Items.FEED_TITLE, 
				ITEMS_TABLE_NAME+"."+FeedData.Items.FEED_TITLE);
		ITEMS_PROJECTION_MAP.put(FeedData.Items.FEED_ID, 
				ITEMS_TABLE_NAME+"."+FeedData.Items.FEED_ID);
		ITEMS_PROJECTION_MAP.put(FeedData.Items.READ_STATE, 
				ITEMS_TABLE_NAME+"."+FeedData.Items.READ_STATE);
		ITEMS_PROJECTION_MAP.put(FeedData.Items.READ_STATE_PENDING, 
				ITEMS_TABLE_NAME+"."+FeedData.Items.READ_STATE_PENDING);
		ITEMS_PROJECTION_MAP.put(FeedData.Items.SHAREED_STATE, 
				ITEMS_TABLE_NAME+"."+FeedData.Items.SHAREED_STATE);
		ITEMS_PROJECTION_MAP.put(FeedData.Items.SHAREED_STATE_PENDING, 
				ITEMS_TABLE_NAME+"."+FeedData.Items.SHAREED_STATE_PENDING);
		ITEMS_PROJECTION_MAP.put(FeedData.Items.STARRED_STATE, 
				ITEMS_TABLE_NAME+"."+FeedData.Items.STARRED_STATE);
		ITEMS_PROJECTION_MAP.put(FeedData.Items.STARRED_STATE_PENDING, 
				ITEMS_TABLE_NAME+"."+FeedData.Items.STARRED_STATE_PENDING);
		ITEMS_PROJECTION_MAP.put(FeedData.Items.LIKED_STATE, 
				ITEMS_TABLE_NAME+"."+FeedData.Items.LIKED_STATE);
		ITEMS_PROJECTION_MAP.put(FeedData.Items.LIKED_STATE_PENDING, 
				ITEMS_TABLE_NAME+"."+FeedData.Items.LIKED_STATE_PENDING);
		ITEMS_PROJECTION_MAP.put(FeedData.Items.DOWNLOAD_STATE, 
				ITEMS_TABLE_NAME+"."+FeedData.Items.DOWNLOAD_STATE);
		ITEMS_PROJECTION_MAP.put(FeedData.Items.UPDATE_TIMESTAMP, 
				ITEMS_TABLE_NAME+"."+FeedData.Items.UPDATE_TIMESTAMP);
		ITEMS_PROJECTION_MAP.put(FeedData.Items.AUTHOR, 
				ITEMS_TABLE_NAME+"."+FeedData.Items.AUTHOR);
		ITEMS_PROJECTION_MAP.put(FeedData.Items.INSERT_TIMESTAMP, 
				ITEMS_TABLE_NAME+"."+FeedData.Items.INSERT_TIMESTAMP);
		ITEMS_PROJECTION_MAP.put(FeedData.Items.PREVIEW_IMG, 
				ITEMS_TABLE_NAME+"."+FeedData.Items.PREVIEW_IMG);
		
		FEEDS_PROJECTION_MAP = new HashMap<String, String>();
		FEEDS_PROJECTION_MAP.put(FeedData.Feeds._ID, 
				FEEDS_TABLE_NAME+"."+FeedData.Feeds._ID);		
		FEEDS_PROJECTION_MAP.put(FeedData.Feeds.ATOM_ID, 
				FEEDS_TABLE_NAME+"."+FeedData.Feeds.ATOM_ID);		
		FEEDS_PROJECTION_MAP.put(FeedData.Feeds.TITLE, 
				FEEDS_TABLE_NAME+"."+FeedData.Feeds.TITLE);		
		FEEDS_PROJECTION_MAP.put(FeedData.Feeds.SORT_ID, 
				FEEDS_TABLE_NAME+"."+FeedData.Feeds.SORT_ID);
		
		LABELS_PROJECTION_MAP = new HashMap<String, String>();
		LABELS_PROJECTION_MAP.put(FeedData.Labels._ID, 
				LABELS_TABLE_NAME+"."+FeedData.Labels._ID);		
		LABELS_PROJECTION_MAP.put(FeedData.Labels.NAME, 
				LABELS_TABLE_NAME+"."+FeedData.Labels.NAME);		
		LABELS_PROJECTION_MAP.put(FeedData.Labels.SORT_ID, 
				LABELS_TABLE_NAME+"."+FeedData.Labels.SORT_ID);
		
		ITEM_LABEL_PROJECTION_MAP = new HashMap<String, String>();
		ITEM_LABEL_PROJECTION_MAP.put(FeedData.Item_label._ID, 
				ITEM_LABEL_TABLE_NAME+"."+FeedData.Item_label._ID);		
		ITEM_LABEL_PROJECTION_MAP.put(FeedData.Item_label.ITEM_ID, 
				ITEM_LABEL_TABLE_NAME+"."+FeedData.Item_label.ITEM_ID);		
		ITEM_LABEL_PROJECTION_MAP.put(FeedData.Item_label.LABEL_ID, 
				ITEM_LABEL_TABLE_NAME+"."+FeedData.Item_label.LABEL_ID);
		
	}
	
	/**
	 * ContentProvider maintain the tables.
	 */
	private static class DatabaseHelper extends SQLiteOpenHelper
	{		

		public DatabaseHelper(Context context) {
			super(context, DATABASE_NAME, null, DATABASE_VERSION);
		}

		@Override
		public void onCreate(SQLiteDatabase db) {
			//TODO database need to be modified. See FeedData class.
			//create table items
			db.execSQL("CREATE TABLE "+ITEMS_TABLE_NAME+" ("+
					FeedData.Items._ID+" INTEGER PRIMARY KEY AUTOINCREMENT, "+
					FeedData.Items.ATOM_ID+" TEXT, "+
					FeedData.Items.ALTERNATE_URL+" TEXT, "+
					FeedData.Items.CONTENT+" TEXT, "+
					FeedData.Items.SUMMARY+" TEXT, "+
					FeedData.Items.TITLE+" TEXT, "+
					FeedData.Items.FEED_TITLE+" TEXT, "+
					FeedData.Items.FEED_ID+" TEXT, "+
					FeedData.Items.READ_STATE+" INTEGER, "+
					FeedData.Items.READ_STATE_PENDING + " INTEGER, "+
					FeedData.Items.SHAREED_STATE+" INTEGER, "+
					FeedData.Items.SHAREED_STATE_PENDING+" INTEGER, "+
					FeedData.Items.STARRED_STATE+" INTEGER, "+
					FeedData.Items.STARRED_STATE_PENDING+" INTEGER, "+
					FeedData.Items.LIKED_STATE+" INTEGER, "+
					FeedData.Items.LIKED_STATE_PENDING+" INTEGER, "+
					FeedData.Items.DOWNLOAD_STATE+" INTEGER, "+
					FeedData.Items.UPDATE_TIMESTAMP+" INTEGER, "+
					FeedData.Items.AUTHOR+" TEXT, "+
					FeedData.Items.PREVIEW_IMG+" TEXT, "+
					FeedData.Items.INSERT_TIMESTAMP+" INTEGER);");
			
			//create table feeds
			db.execSQL("CREATE TABLE "+FEEDS_TABLE_NAME+" ("+
					FeedData.Feeds._ID+" INTEGER PRIMARY KEY AUTOINCREMENT, "+
					FeedData.Feeds.ATOM_ID+" TEXT, "+
					FeedData.Feeds.TITLE+" TEXT, "+
					FeedData.Feeds.SORT_ID+" INTEGER);"
					);
			
			//create table labels
			db.execSQL("CREATE TABLE "+ LABELS_TABLE_NAME+" ("+
					FeedData.Labels._ID+" INTEGER PRIMARY KEY AUTOINCREMENT, "+
					FeedData.Labels.NAME+" TEXT, "+
					FeedData.Labels.SORT_ID+" INTEGER);");
			
			//create table item_label
			db.execSQL("CREATE TABLE "+ITEM_LABEL_TABLE_NAME+" ("+
					FeedData.Item_label._ID+" INTEGER PRIMARY KEY AUTOINCREMENT, "+
					FeedData.Item_label.ITEM_ID+" INTEGER, "+
					FeedData.Item_label.LABEL_ID+" INTEGER);");
		}

		@Override
		public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
			Log.w(TAG, "upgrading database from version "+oldVersion+" to "
					+newVersion+".");
			
			if(newVersion > oldVersion){
				//TODO When we have a new version of database,
				//DO upgrades.
				
				//drop all old tables and recreate them.
				db.execSQL("DROP TABLE IF EXISTS "+ITEMS_TABLE_NAME);
				db.execSQL("DROP TABLE IF EXISTS "+FEEDS_TABLE_NAME);
				db.execSQL("DROP TABLE IF EXISTS "+LABELS_TABLE_NAME);
				db.execSQL("DROP TABLE IF EXISTS "+ITEM_LABEL_TABLE_NAME);
				onCreate(db);
			}else
			{
				Log.w(TAG, "Downgrade database. Do nothing.");
			}
		}
		
	}
	@Override
	public int delete(Uri uri, String selection, String[] selectionArgs) {
		SQLiteDatabase db = mOpenHelper.getWritableDatabase();
		int count;
		switch (URL_MATCHER.match(uri)) {
		case ITEMS:
			count = db.delete(ITEMS_TABLE_NAME, selection, selectionArgs);
			break;
		case ITEM_ID:
			String keyID = getPathSegment(uri);
			String whereClause = getWhereString(selection);
			count = db.delete(ITEMS_TABLE_NAME, 
					ITEMS_PROJECTION_MAP.get(FeedData.Items._ID)+" = "+ 
					keyID + whereClause, selectionArgs);
			break;
		case FEEDS:
			count = db.delete(FEEDS_TABLE_NAME, selection, selectionArgs);
			break;
		case FEED_ID:
			keyID = getPathSegment(uri);
			whereClause = getWhereString(selection);
			count = db.delete(FEEDS_TABLE_NAME,
					FEEDS_PROJECTION_MAP.get(FeedData.Feeds._ID)+" = " +
					keyID + whereClause, selectionArgs);
			break;
		case LABELS:
			count = db.delete(LABELS_TABLE_NAME, selection, selectionArgs);
			break;
		case LABEL_ID:
			keyID = getPathSegment(uri);
			whereClause = getWhereString(selection);
			count = db.delete(LABELS_TABLE_NAME,
					LABELS_PROJECTION_MAP.get(FeedData.Labels._ID)+" = " +
					keyID + whereClause, selectionArgs);
			break;
		case ITEM_LABELS:
			count = db.delete(ITEM_LABEL_TABLE_NAME, selection, selectionArgs);
			break;
		case ITEM_LABEL_ID:
			keyID = getPathSegment(uri);
			whereClause = getWhereString(selection);
			count = db.delete(ITEM_LABEL_TABLE_NAME,
					ITEM_LABEL_PROJECTION_MAP.get(FeedData.Item_label._ID) + " = " +
					keyID + whereClause, selectionArgs);
			break;
		default:
			throw new IllegalArgumentException("Unknown URI: "+uri);
		}
		getContext().getContentResolver().notifyChange(uri, null);
		return count;
	}
	
	/**
	 * 返回uri的参数值，仅限于authority/path/number情况
	 * @param uri uri地址
	 * @return uri的参数值
	 */
	private String getPathSegment(Uri uri){
		return uri.getPathSegments().get(1);
	}
	
	/**
	 * 用于 拼接where字句，
	 * @param selectionString
	 * @return " and ( selection )"或者""
	 */
	private String getWhereString(String selectionString){
		String whereString;
		if (!TextUtils.isEmpty(selectionString)) {
			whereString = " AND (" + selectionString + ')';
		}else {
			whereString = "";
		}
		return whereString;
	}

	@Override
	public String getType(Uri uri) {
		switch(URL_MATCHER.match(uri)){
		case ITEMS: 
			return FeedData.Items.CONTENT_TYPE;
		case ITEM_ID: 
			return FeedData.Items.CONTENT_ITEM_TYPE;
		case FEEDS: 
			return FeedData.Feeds.CONTENT_TYPE;
		case FEED_ID: 
			return FeedData.Feeds.CONTENT_ITEM_TYPE;
		case LABELS: 
			return FeedData.Labels.CONTENT_TYPE;
		case LABEL_ID: 
			return FeedData.Labels.CONTENT_ITEM_TYPE;
		case ITEM_LABELS:
			return FeedData.Item_label.CONTENT_TYPE;
		case ITEM_LABEL_ID:
			return FeedData.Item_label.CONTENT_ITEM_TYPE;
		case ITEMS_BY_LABEL: 
			return FeedData.Items.CONTENT_TYPE;
		default:
			throw new IllegalArgumentException("Unknown URI "+uri);
		}
	}

	@Override
	public Uri insert(Uri uri, ContentValues values) {
		ContentValues pValues;
		if(values != null)
		{
			pValues = values;
		}
		else {
			pValues = new ContentValues();
		}
		switch (URL_MATCHER.match(uri)) {
		case ITEMS:
			return insertItem(pValues);
		case FEEDS:
			return insertFeed(pValues);
		case LABELS:
			return insertLabel(pValues);
		case ITEM_LABELS:
			return insertItemLabel(pValues);
		default:
			throw new IllegalArgumentException("Unknow URi: " + uri);
		}
	}
	
	private Uri insertItem(ContentValues values){
		SQLiteDatabase db = mOpenHelper.getWritableDatabase();
		long rowID;
		
		/**
		 * Timestamp for insert action
		 */
		Long now = Long.valueOf(System.currentTimeMillis());
		
		//make sure every field has a value.
		if(!values.containsKey(FeedData.Items.ATOM_ID))
		{
			values.put(FeedData.Items.ATOM_ID, "");			
		}
		if(!values.containsKey(FeedData.Items.CONTENT))
		{
			values.put(FeedData.Items.CONTENT, "");
		}
		if (!values.containsKey(FeedData.Items.SUMMARY)) {
			values.put(FeedData.Items.SUMMARY, "");
		}
		if (!values.containsKey(FeedData.Items.FEED_ID)) {
			values.put(FeedData.Items.FEED_ID, 0);
		}
		if (!values.containsKey(FeedData.Items.FEED_TITLE)) {
			values.put(FeedData.Items.FEED_TITLE, "");
		}
		if (!values.containsKey(FeedData.Items.ALTERNATE_URL)) {
			values.put(FeedData.Items.ALTERNATE_URL, "#");
		}
		if (!values.containsKey(FeedData.Items.TITLE)) {
			values.put(FeedData.Items.TITLE, "");
		}
		if (!values.containsKey(FeedData.Items.READ_STATE)) {
			values.put(FeedData.Items.READ_STATE,0);
		}
		if(!values.containsKey(FeedData.Items.READ_STATE_PENDING)){
			values.put(FeedData.Items.READ_STATE_PENDING, 0);
		}
		if (!values.containsKey(FeedData.Items.SHAREED_STATE)) {
			values.put(FeedData.Items.SHAREED_STATE, 0);
		}
		if(!values.containsKey(FeedData.Items.SHAREED_STATE_PENDING)){
			values.put(FeedData.Items.SHAREED_STATE_PENDING, 0);
		}
		if (!values.containsKey(FeedData.Items.STARRED_STATE)) {
			values.put(FeedData.Items.STARRED_STATE, 0);
		}
		if(!values.containsKey(FeedData.Items.STARRED_STATE_PENDING)){
			values.put(FeedData.Items.STARRED_STATE_PENDING, 0);
		}
		if (!values.containsKey(FeedData.Items.LIKED_STATE)) {
			values.put(FeedData.Items.LIKED_STATE, 0);
		}
		if(!values.containsKey(FeedData.Items.LIKED_STATE_PENDING)){
			values.put(FeedData.Items.LIKED_STATE_PENDING, 0);
		}
		if(!values.containsKey(FeedData.Items.DOWNLOAD_STATE)){
			values.put(FeedData.Items.DOWNLOAD_STATE, 0);
		}
		if (!values.containsKey(FeedData.Items.UPDATE_TIMESTAMP)) {
			values.put(FeedData.Items.UPDATE_TIMESTAMP, now);
		}
		if (!values.containsKey(FeedData.Items.INSERT_TIMESTAMP)) {
			values.put(FeedData.Items.INSERT_TIMESTAMP, now);
		}
		if (!values.containsKey(FeedData.Items.AUTHOR)) {
			values.put(FeedData.Items.AUTHOR, "");
		}
		if(!values.containsKey(FeedData.Items.PREVIEW_IMG)){
			values.put(FeedData.Items.PREVIEW_IMG, "");
		}
		
		//insert into database.
		rowID = db.insert(ITEMS_TABLE_NAME, ITEMS_PROJECTION_MAP.get(FeedData.Items.ATOM_ID),
				values);
		
		if (rowID > 0) {
			Uri uri = ContentUris.withAppendedId(FeedData.Items.CONTENT_URI, rowID);
			getContext().getContentResolver().notifyChange(uri, null);
			return uri;
		}
		
		//normally, we should not reach this far.
		throw new SQLException("Failed to insert into table: "+ITEMS_TABLE_NAME);
	}

	private Uri insertFeed(ContentValues values) {
		SQLiteDatabase db = mOpenHelper.getWritableDatabase();
		long rowID;
		
		if (!values.containsKey(FeedData.Feeds.ATOM_ID)) {
			values.put(FeedData.Feeds.ATOM_ID, "");
		}
		if (!values.containsKey(FeedData.Feeds.TITLE)) {
			values.put(FeedData.Feeds.TITLE, "");
		}
		if (!values.containsKey(FeedData.Feeds.SORT_ID)) {
			values.put(FeedData.Feeds.SORT_ID, 0);
		}
		
		rowID = db.insert(FEEDS_TABLE_NAME, FeedData.Feeds.ATOM_ID, values);
		if (rowID > 0) {
			Uri uri = ContentUris.withAppendedId(FeedData.Feeds.CONTENT_URI, rowID);
			getContext().getContentResolver().notifyChange(uri, null);
			return uri;
		}
		
		throw new SQLException("Failed to insert into table: "+FEEDS_TABLE_NAME);
	}
	
	private Uri insertLabel(ContentValues values) {
		SQLiteDatabase db = mOpenHelper.getWritableDatabase();
		long rowID;
		
		if (!values.containsKey(FeedData.Labels.NAME)) {
			values.put(FeedData.Labels.NAME, "");
		}
		if (!values.containsKey(FeedData.Labels.SORT_ID)) {
			values.put(FeedData.Labels.SORT_ID, 0);
		}
		
		rowID = db.insert(LABELS_TABLE_NAME, 
				LABELS_PROJECTION_MAP.get(FeedData.Labels.NAME), values);
		if (rowID > 0) {
			Uri uri = ContentUris.withAppendedId(FeedData.Labels.CONTENT_URI, rowID);
			getContext().getContentResolver().notifyChange(uri, null);
			return uri;
		}
		
		throw new SQLException("Failed to insert into Table: "+LABELS_TABLE_NAME);
	}
	
	private Uri insertItemLabel(ContentValues values){
		SQLiteDatabase db = mOpenHelper.getWritableDatabase();
		long rowID;
		
		if (!values.containsKey(FeedData.Item_label.ITEM_ID)) {
			values.put(FeedData.Item_label.ITEM_ID, 0);
		}
		if (!values.containsKey(FeedData.Item_label.LABEL_ID)) {
			values.put(FeedData.Item_label.LABEL_ID, 0);
		}
		
		rowID = db.insert(ITEM_LABEL_TABLE_NAME, 
				ITEM_LABEL_PROJECTION_MAP.get(FeedData.Item_label.ITEM_ID), values);
		
		if (rowID > 0) {
			Uri uri = ContentUris.withAppendedId(FeedData.Item_label.CONTENT_URI, rowID);
			getContext().getContentResolver().notifyChange(uri, null);
			return uri;
		}
		
		throw new SQLException("Failed to insert into Table: "+ITEM_LABEL_TABLE_NAME);
	}
	
	@Override
	public boolean onCreate() {
		mOpenHelper = new DatabaseHelper(getContext());
		return true;
	}

	@Override
	public Cursor query(Uri uri, String[] projection, String selection,
			String[] selectionArgs, String sortOrder) {
		SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
		String defaultOrderBy = null;
		
		switch(URL_MATCHER.match(uri)){
		case ITEMS:
			qb.setTables(ITEMS_TABLE_NAME);
			qb.setProjectionMap(ITEMS_PROJECTION_MAP);
			defaultOrderBy = FeedData.Items.DEFAULT_SORT_ORDER;
			break;
		case ITEM_ID:
			qb.setTables(ITEMS_TABLE_NAME);
			qb.setProjectionMap(ITEMS_PROJECTION_MAP);
			defaultOrderBy = FeedData.Items.DEFAULT_SORT_ORDER;
			qb.appendWhere(FeedData.Items._ID + " = " +
					uri.getPathSegments().get(1));			
			break;
		case FEEDS:
			qb.setTables(FEEDS_TABLE_NAME);
			qb.setProjectionMap(FEEDS_PROJECTION_MAP);
			defaultOrderBy = FeedData.Feeds.DEFAULT_SORT_ORDER;
			break;
		case FEED_ID:
			qb.setTables(FEEDS_TABLE_NAME);
			qb.setProjectionMap(FEEDS_PROJECTION_MAP);
			defaultOrderBy = FeedData.Feeds.DEFAULT_SORT_ORDER;
			qb.appendWhere(FeedData.Feeds._ID + " = " +
					uri.getPathSegments().get(1));
			break;
		case LABELS:
			qb.setTables(LABELS_TABLE_NAME);
			qb.setProjectionMap(LABELS_PROJECTION_MAP);
			defaultOrderBy = FeedData.Labels.DEFAULT_SORT_ORDER;
			break;
		case LABEL_ID:
			qb.setTables(LABELS_TABLE_NAME);
			qb.setProjectionMap(LABELS_PROJECTION_MAP);
			defaultOrderBy = FeedData.Labels.DEFAULT_SORT_ORDER;
			qb.appendWhere(FeedData.Labels._ID + " = " +
					uri.getPathSegments().get(1));
			break;
		case ITEM_LABELS:
			qb.setTables(ITEM_LABEL_TABLE_NAME);
			qb.setProjectionMap(ITEM_LABEL_PROJECTION_MAP);
			defaultOrderBy = FeedData.Item_label.DEFAULT_SORT_ORDER;
			break;
		case ITEM_LABEL_ID:
			qb.setTables(ITEM_LABEL_TABLE_NAME);
			qb.setProjectionMap(ITEM_LABEL_PROJECTION_MAP);
			defaultOrderBy = FeedData.Item_label.DEFAULT_SORT_ORDER;
			qb.appendWhere(FeedData.Item_label._ID + " = " + 
					uri.getPathSegments().get(1));
			break;
		case ITEMS_BY_LABEL:
			qb.setTables(ITEMS_TABLE_NAME+", "+ITEM_LABEL_TABLE_NAME);
			qb.setProjectionMap(ITEM_LABEL_PROJECTION_MAP);
			defaultOrderBy = FeedData.Items.DEFAULT_SORT_ORDER;
			qb.appendWhere(ITEMS_TABLE_NAME+"."+FeedData.Items._ID+" = "+
					ITEMS_TABLE_NAME+"."+FeedData.Item_label.ITEM_ID + " AND "+
					ITEM_LABEL_TABLE_NAME+"."+FeedData.Item_label.LABEL_ID +" = "
					+ uri.getPathSegments().get(2));
			break;
			default:
				throw new IllegalArgumentException("Unknow URI: " + uri);
		}
		
		String order;
		if(TextUtils.isEmpty(sortOrder))
		{
			order = defaultOrderBy;
		}
		else
		{
			order = sortOrder;
		}
		
		SQLiteDatabase db = mOpenHelper.getReadableDatabase();
		Cursor c = qb.query(db, projection, selection, selectionArgs, null, null, order);
		c.setNotificationUri(getContext().getContentResolver(), uri);
		return c;
	}

	@Override
	public int update(Uri uri, ContentValues values, String selection,
			String[] selectionArgs) {
		SQLiteDatabase db = mOpenHelper.getWritableDatabase();
		
		int count;
		switch (URL_MATCHER.match(uri)) {
		case ITEMS:
			count = db.update(ITEMS_TABLE_NAME, values, selection, selectionArgs);
			break;
		case ITEM_ID:
			String keyID = getPathSegment(uri);
			String whereClause = getWhereString(selection);
			count = db.update(ITEMS_TABLE_NAME, values, 
					ITEMS_PROJECTION_MAP.get(FeedData.Items._ID) + " = " +
					keyID + whereClause, selectionArgs);
			break;
		case FEEDS:
			count = db.update(FEEDS_TABLE_NAME, values, selection, selectionArgs);
			break;
		case FEED_ID:
			keyID = getPathSegment(uri);
			whereClause = getWhereString(selection);
			count = db.update(FEEDS_TABLE_NAME, values, 
					FEEDS_PROJECTION_MAP.get(FeedData.Feeds._ID)+" = "+
					keyID+whereClause, selectionArgs);
			break;
		case LABELS:
			count = db.update(LABELS_TABLE_NAME, values, selection, selectionArgs);
			break;
		case LABEL_ID:
			keyID = getPathSegment(uri);
			whereClause = getWhereString(selection);
			count = db.update(LABELS_TABLE_NAME, values, 
					LABELS_PROJECTION_MAP.get(FeedData.Labels._ID)+ " = "+ 
					keyID + whereClause, selectionArgs);
			break;
		case ITEM_LABELS:
			count = db.update(ITEM_LABEL_TABLE_NAME, values, selection, selectionArgs);
			break;
		case ITEM_LABEL_ID:
			keyID = getPathSegment(uri);
			whereClause = getWhereString(selection);
			count = db.update(ITEM_LABEL_TABLE_NAME, values, 
					ITEM_LABEL_PROJECTION_MAP.get(FeedData.Item_label._ID)+" = " +
					keyID+whereClause, selectionArgs);
			break;
		default:
			throw new IllegalArgumentException("Unknow URI: " + uri);
		}
		
		getContext().getContentResolver().notifyChange(uri, null);
		return count;
	}

}
